﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;


namespace Powerpoint
{
    public class ConnectionHandler
    {
        private StateObject state;
        public bool connected = false;
        private String ipAddress;
        private Int32 port;
        public ManualResetEvent doneDone = new ManualResetEvent(false);
        public ManualResetEvent sendDone = new ManualResetEvent(false);
        public ManualResetEvent receiveDone = new ManualResetEvent(false);

        public static ArrayList conArr = null;

        private ArrayList objToSend = null;

        public ConnectionHandler(StateObject stateObj)
        {
            if (ConnectionHandler.conArr == null)
            {
                ConnectionHandler.conArr = new ArrayList();
            }

            state = stateObj;
            connected = true;
            ipAddress = ((IPEndPoint)state.workSocket.RemoteEndPoint).Address.ToString();
            port = ((IPEndPoint)state.workSocket.RemoteEndPoint).Port;
            ConnectionHandler.conArr.Add(this);
            //Console.WriteLine("------------ New Connection Handler created. Processing...");

            objToSend = new ArrayList();
        }

        public void addStringData(String data)
        {
            byte[] ascii = System.Text.Encoding.ASCII.GetBytes(data);

            lock (objToSend.SyncRoot)
            {
                this.objToSend.Add(ascii);
                //Client.newEvent("Neues String Paket hinzugefügt.");
            }
        }

        public void addByteData(byte[] data)
        {
            lock (objToSend.SyncRoot)
            {
                this.objToSend.Add(data);
            }
            //Client.newEvent("Neues Byte Paket hinzugefügt.");
        }

        public void sendThread()
        {
            while (true && state.workSocket.Connected && connected)
            {
                sendDone.Reset();

                ArrayList sendNow = new ArrayList();
                lock (objToSend.SyncRoot)
                {
                    // Console.WriteLine("{0} Elements in objToSend!", objToSend.Count);
                    sendNow = (ArrayList)objToSend.Clone();
                    objToSend.Clear();
                }

                while (sendNow.Count > 0)
                {
                    foreach (byte[] data in sendNow)
                    {
                        Client.Send(state.workSocket, data, state);
                        sendDone.WaitOne();
                    }
                    sendNow.Clear();
                }
                Thread.Sleep(5);
            }
            Console.WriteLine("Sending Thread ended.");
        }

        public void receiveThread()
        {
            while (true && state.workSocket.Connected && connected)
            {
                receiveDone.Reset();
                Client.Receive(state.workSocket, state);
                receiveDone.WaitOne();
                Thread.Sleep(1);
            }
            Console.WriteLine("Receiving Thread ended.");
        }

        public void setReceiveDone()
        {
            receiveDone.Set();
        }

        public void setSendDone()
        {
            sendDone.Set();
        }

        public String getIpString()
        {
            return ipAddress;
        }

        public Int32 getPortInt()
        {
            return port;
        }

        public void closeConnection()
        {
            connected = false;
            ConnectionHandler.conArr.Remove(this);
            Console.WriteLine("------------ ConnectionHandler closed: {0}:{1}", getIpString(), getPortInt());
        }

        public void printConnectionList()
        {
            foreach (ConnectionHandler cHandl in ConnectionHandler.conArr)
            {
                Console.WriteLine("@@ {0}:{1}", cHandl.getIpString(), cHandl.getPortInt());
            }
        }
    }
}
